"""
通用评论API路由
"""
from typing import Dict, Any, Optional
from fastapi import APIRouter, Depends, HTTPException, status  # pyright: ignore[reportMissingImports]
from fastapi.responses import JSONResponse  # pyright: ignore[reportMissingImports]
from pydantic import BaseModel  # pyright: ignore[reportMissingImports]

from app.api.deps import get_current_user, get_db
from app.services.comment_service import CommentService
from app.services.permission_service import PermissionService, Permissions
from app.services.notification_service import NotificationService
from app.models.notification import NotificationCreate, NotificationType, RelatedObjectType
from app.core.response import success_response
import asyncio
import logging

router = APIRouter()
logger = logging.getLogger(__name__)


# 评论创建请求模型
class CommentCreate(BaseModel):
    content: str
    parent_comment_id: Optional[str] = None
    status: Optional[str] = None


# 评论更新请求模型
class CommentUpdate(BaseModel):
    content: Optional[str] = None
    status: Optional[str] = None
    is_deleted: Optional[bool] = None


# 评论列表查询参数
class CommentQuery(BaseModel):
    page: int = 1
    page_size: int = 20
    include_deleted: bool = False


def get_comment_service(db = Depends(get_db)) -> CommentService:
    """获取评论服务实例"""
    return CommentService(db)


def normalize_entity_type(entity_type: str) -> str:
    """将复数形式的实体类型转换为单数形式"""
    plural_to_singular = {
        "tasks": "task",
        "requirements": "requirement",
        "defects": "defect"
    }
    return plural_to_singular.get(entity_type, entity_type)


@router.post("/{entity_type}/{entity_id}/comments", response_model=Dict[str, Any])
async def add_comment(
    entity_type: str,
    entity_id: str,
    comment_in: CommentCreate,
    current_user: dict = Depends(get_current_user),
    comment_service: CommentService = Depends(get_comment_service),
    db = Depends(get_db)
):
    """
    添加评论
    需要权限：comment:create
    
    Args:
        entity_type: 实体类型（task, requirement, defect）
        entity_id: 实体ID
        comment_in: 评论创建数据
        current_user: 当前用户信息
        comment_service: 评论服务实例
        db: 数据库连接
    
    Returns:
        添加评论的结果
    """
    # 检查权限
    if not PermissionService.has_permission(current_user, Permissions.COMMENT_CREATE):
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="权限不足: 需要 comment:create 权限"
        )
    
    # 规范化实体类型（支持复数形式）
    normalized_type = normalize_entity_type(entity_type)
    
    # 验证实体类型
    valid_entity_types = ["task", "requirement", "defect", "test_case", "document"]
    if normalized_type not in valid_entity_types:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"无效的实体类型，支持的类型: {', '.join(valid_entity_types)}"
        )
    
    # 如果实体有关联项目，检查项目访问权限
    from bson import ObjectId  # pyright: ignore[reportMissingImports]
    collection_name = f"{normalized_type}s"
    entity = await db[collection_name].find_one({"_id": ObjectId(entity_id)})
    if entity and entity.get("project_id"):
        project_id = str(entity["project_id"])
        has_access = await PermissionService.check_project_access(
            project_id=project_id,
            user=current_user,
            db=db
        )
        if not has_access:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="权限不足: 无法访问该项目"
            )
    
    # 调用服务层方法
    result = await comment_service.add_comment(
        user=current_user,
        entity_type=normalized_type,
        entity_id=entity_id,
        comment_in=comment_in.dict()
    )
    
    # 发送评论通知
    try:
        from bson import ObjectId
        user_id = ObjectId(current_user["user_id"])
        current_user_obj = await db.users.find_one({"_id": user_id})
        current_user_name = current_user_obj.get("name") or current_user_obj.get("username", "未知用户") if current_user_obj else "未知用户"
        
        # 获取实体信息
        entity_obj_id = ObjectId(entity_id)
        collection_name = f"{normalized_type}s"
        entity = await db[collection_name].find_one({"_id": entity_obj_id})
        if not entity:
            logger.warning(f"实体不存在，无法发送通知: {entity_id}")
            return success_response(
                data={"id": result.get("comment", {}).get("id")} if result.get("comment") else None,
                message=result.get("message", "评论添加成功")
            )
        
        # 构建实体标题（根据实体类型获取标题字段）
        entity_title = entity.get("title") or entity.get("name") or f"{normalized_type.capitalize()} #{entity_id[:8]}"
        
        # 确定通知接收者集合
        notification_recipients = set()
        
        # 1. 实体创建人（如果不是当前用户）
        if entity.get("created_by"):
            creator_id = entity["created_by"]
            if str(creator_id) != current_user["user_id"]:
                notification_recipients.add(str(creator_id))
        
        # 2. 实体负责人（如果是任务或缺陷）
        if normalized_type in ["task", "defect"] and entity.get("assignee_id"):
            assignee_id = entity["assignee_id"]
            if str(assignee_id) != current_user["user_id"]:
                notification_recipients.add(str(assignee_id))
        
        # 3. 需求报告人（如果是需求）
        if normalized_type == "requirement" and entity.get("reporter_id"):
            reporter_id = entity["reporter_id"]
            if str(reporter_id) != current_user["user_id"]:
                notification_recipients.add(str(reporter_id))
        
        # 4. 如果是回复评论，通知父评论作者
        if comment_in.parent_comment_id:
            comments_list = entity.get("comments", [])
            parent_comment = next(
                (c for c in comments_list if c.get("id") == comment_in.parent_comment_id),
                None
            )
            if parent_comment:
                parent_author_id = parent_comment.get("author_id") or parent_comment.get("user_id")
                if parent_author_id and str(parent_author_id) != current_user["user_id"]:
                    notification_recipients.add(str(parent_author_id))
        
        # 5. 如果是任务，也通知任务的创建人
        if normalized_type == "task" and entity.get("created_by"):
            creator_id = entity["created_by"]
            if str(creator_id) != current_user["user_id"]:
                notification_recipients.add(str(creator_id))
        
        # 移除当前用户
        notification_recipients.discard(current_user["user_id"])
        
        # 发送通知
        notification_tasks = []
        comment_type = NotificationType.COMMENT_ADDED
        if comment_in.parent_comment_id:
            comment_type = NotificationType.COMMENT_REPLIED
        
        # 确定关联对象类型
        related_type_map = {
            "task": RelatedObjectType.TASK,
            "requirement": RelatedObjectType.REQUIREMENT,
            "defect": RelatedObjectType.DEFECT,
            "test_case": RelatedObjectType.TEST_CASE,
            "document": RelatedObjectType.DOCUMENT
        }
        related_type = related_type_map.get(normalized_type)
        
        # 构建通知内容
        comment_content_preview = comment_in.content[:50] + "..." if len(comment_in.content) > 50 else comment_in.content
        
        for recipient_id in notification_recipients:
            if comment_in.parent_comment_id:
                # 回复通知
                notification_data = NotificationCreate(
                    user_id=recipient_id,
                    type=comment_type,
                    title=f"回复了您的评论：{entity_title}",
                    content=f"{current_user_name} 回复了您在「{entity_title}」中的评论：{comment_content_preview}",
                    related_type=related_type,
                    related_id=entity_id,
                    metadata={
                        "comment_id": result.get("comment", {}).get("id"),
                        "parent_comment_id": comment_in.parent_comment_id,
                        "operator_id": current_user["user_id"],
                        "operator_name": current_user_name,
                        "operator_avatar": current_user_obj.get("avatar") if current_user_obj else None
                    }
                )
            else:
                # 新增评论通知
                notification_data = NotificationCreate(
                    user_id=recipient_id,
                    type=comment_type,
                    title=f"评论了：{entity_title}",
                    content=f"{current_user_name} 评论了「{entity_title}」：{comment_content_preview}",
                    related_type=related_type,
                    related_id=entity_id,
                    metadata={
                        "comment_id": result.get("comment", {}).get("id"),
                        "operator_id": current_user["user_id"],
                        "operator_name": current_user_name,
                        "operator_avatar": current_user_obj.get("avatar") if current_user_obj else None
                    }
                )
            
            notification_tasks.append(
                NotificationService.create_notification(
                    db=db,
                    notification_data=notification_data,
                    send_email=False
                )
            )
        
        # 异步发送所有通知
        if notification_tasks:
            asyncio.create_task(asyncio.gather(*notification_tasks, return_exceptions=True))
    except Exception as e:
        logger.warning(f"发送评论通知失败: {str(e)}")
    
    return success_response(
        data={"id": result.get("comment", {}).get("id")} if result.get("comment") else None,
        message=result.get("message", "评论添加成功")
    )


@router.put("/{entity_type}/{entity_id}/comments/{comment_id}", response_model=Dict[str, Any])
async def update_comment(
    entity_type: str,
    entity_id: str,
    comment_id: str,
    comment_update: CommentUpdate,
    current_user: dict = Depends(get_current_user),
    comment_service: CommentService = Depends(get_comment_service),
    db = Depends(get_db)
):
    """
    更新评论
    需要权限：comment:update（只能更新自己的评论，或拥有comment:delete权限）
    
    Args:
        entity_type: 实体类型
        entity_id: 实体ID
        comment_id: 评论ID
        comment_update: 评论更新数据
        current_user: 当前用户信息
        comment_service: 评论服务实例
        db: 数据库连接
    
    Returns:
        更新评论的结果
    """
    # 规范化实体类型（支持复数形式）
    normalized_type = normalize_entity_type(entity_type)
    
    # 验证实体类型
    valid_entity_types = ["task", "requirement", "defect", "test_case", "document"]
    if normalized_type not in valid_entity_types:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"无效的实体类型，支持的类型: {', '.join(valid_entity_types)}"
        )
    
    # 检查评论是否存在并获取评论信息
    from bson import ObjectId  # pyright: ignore[reportMissingImports]
    collection_name = f"{normalized_type}s"
    entity = await db[collection_name].find_one({"_id": ObjectId(entity_id)})
    if not entity:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"{normalized_type.capitalize()}不存在"
        )
    
    comments = entity.get("comments", [])
    comment = next((c for c in comments if c.get("id") == comment_id), None)
    if not comment:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="评论不存在"
        )
    
    # 检查权限：只能更新自己的评论，或拥有comment:delete权限（可以更新任何评论）
    user_id = current_user.get("user_id")
    comment_author_id = comment.get("author_id") or comment.get("user_id")
    
    is_own_comment = str(comment_author_id) == user_id
    has_update_permission = PermissionService.has_permission(current_user, Permissions.COMMENT_UPDATE)
    has_delete_permission = PermissionService.has_permission(current_user, Permissions.COMMENT_DELETE)
    
    if not (is_own_comment and has_update_permission) and not has_delete_permission:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="权限不足: 只能更新自己的评论"
        )
    
    # 调用服务层方法
    result = await comment_service.update_comment(
        user=current_user,
        entity_type=normalized_type,
        entity_id=entity_id,
        comment_id=comment_id,
        comment_update=comment_update.dict()
    )
    
    return success_response(
        message=result.get("message", "评论更新成功")
    )


@router.delete("/{entity_type}/{entity_id}/comments/{comment_id}", response_model=Dict[str, Any])
async def delete_comment(
    entity_type: str,
    entity_id: str,
    comment_id: str,
    permanent: bool = False,
    current_user: dict = Depends(get_current_user),
    comment_service: CommentService = Depends(get_comment_service),
    db = Depends(get_db)
):
    """
    删除评论
    需要权限：comment:delete（只能删除自己的评论，或拥有comment:delete权限）
    
    Args:
        entity_type: 实体类型
        entity_id: 实体ID
        comment_id: 评论ID
        permanent: 是否永久删除（默认软删除）
        current_user: 当前用户信息
        comment_service: 评论服务实例
        db: 数据库连接
    
    Returns:
        删除评论的结果
    """
    # 规范化实体类型（支持复数形式）
    normalized_type = normalize_entity_type(entity_type)
    
    # 验证实体类型
    valid_entity_types = ["task", "requirement", "defect", "test_case", "document"]
    if normalized_type not in valid_entity_types:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"无效的实体类型，支持的类型: {', '.join(valid_entity_types)}"
        )
    
    # 检查评论是否存在并获取评论信息
    from bson import ObjectId  # pyright: ignore[reportMissingImports]
    collection_name = f"{normalized_type}s"
    entity = await db[collection_name].find_one({"_id": ObjectId(entity_id)})
    if not entity:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"{normalized_type.capitalize()}不存在"
        )
    
    comments = entity.get("comments", [])
    comment = next((c for c in comments if c.get("id") == comment_id), None)
    if not comment:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="评论不存在"
        )
    
    # 检查权限：只能删除自己的评论，或拥有comment:delete权限（可以删除任何评论）
    user_id = current_user.get("user_id")
    comment_author_id = comment.get("author_id") or comment.get("user_id")
    
    is_own_comment = str(comment_author_id) == user_id
    has_delete_permission = PermissionService.has_permission(current_user, Permissions.COMMENT_DELETE)
    
    if not is_own_comment and not has_delete_permission:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="权限不足: 只能删除自己的评论"
        )
    
    # 调用服务层方法
    result = await comment_service.delete_comment(
        user=current_user,
        entity_type=normalized_type,
        entity_id=entity_id,
        comment_id=comment_id,
        permanent=permanent
    )
    
    return success_response(
        message=result.get("message", "删除评论成功")
    )


@router.get("/{entity_type}/{entity_id}/comments", response_model=Dict[str, Any])
async def get_comments(
    entity_type: str,
    entity_id: str,
    page: int = 1,
    page_size: int = 20,
    include_deleted: bool = False,
    current_user: dict = Depends(get_current_user),
    comment_service: CommentService = Depends(get_comment_service),
    db = Depends(get_db)
):
    """
    获取评论列表
    需要权限：comment:read
    
    Args:
        entity_type: 实体类型
        entity_id: 实体ID
        page: 页码（默认1）
        page_size: 每页数量（默认20）
        include_deleted: 是否包含已删除评论（默认不包含）
        current_user: 当前用户信息
        comment_service: 评论服务实例
        db: 数据库连接
    
    Returns:
        评论列表数据
    """
    # 检查权限
    if not PermissionService.has_permission(current_user, Permissions.COMMENT_READ):
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="权限不足: 需要 comment:read 权限"
        )
    
    # 规范化实体类型（支持复数形式）
    normalized_type = normalize_entity_type(entity_type)
    
    # 验证实体类型
    valid_entity_types = ["task", "requirement", "defect", "test_case", "document"]
    if normalized_type not in valid_entity_types:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"无效的实体类型，支持的类型: {', '.join(valid_entity_types)}"
        )
    
    # 如果实体有关联项目，检查项目访问权限
    from bson import ObjectId  # pyright: ignore[reportMissingImports]
    collection_name = f"{normalized_type}s"
    entity = await db[collection_name].find_one({"_id": ObjectId(entity_id)})
    if entity and entity.get("project_id"):
        project_id = str(entity["project_id"])
        has_access = await PermissionService.check_project_access(
            project_id=project_id,
            user=current_user,
            db=db
        )
        if not has_access:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="权限不足: 无法访问该项目"
            )
    
    # 验证分页参数
    if page < 1:
        page = 1
    if page_size < 1 or page_size > 100:
        page_size = 20
    
    # 调用服务层方法
    result = await comment_service.get_comments(
        entity_type=normalized_type,
        entity_id=entity_id,
        page=page,
        page_size=page_size,
        include_deleted=include_deleted
    )
    
    return success_response(
        data={
            "items": result.get("items", []),
            "total": result.get("total", 0),
            "page": result.get("page", page),
            "page_size": result.get("page_size", page_size)
        },
        message=result.get("message", "获取评论列表成功")
    )
